package worm

import (
	"cloud_worm/wormweb/controllers/ctrconfig"
	"fmt"
	"cloud_worm/util/uhttp"
	"path/filepath"
	"cloud_worm/util/umodels/mysqldb"
	"cloud_worm/util/umodels/mysqldb/dbmanager"
	"cloud_worm/wormweb/controllers/ctrutil"
	"os"
	"io"
	"github.com/astaxie/beego/logs"
	"cloud_worm/util/ufile"
	"strings"
	"time"
	"io/ioutil"
	"encoding/json"
)

type PackageController struct {
	ctrconfig.LoginCtr
}

// PackageController.Upload 包文件上传
func (p *PackageController) Upload()  {
	p.Manager()

	fp, handle, err := p.Ctx.Request.FormFile("file")
	if err != nil {
		errMsg := fmt.Sprintf("read form file error: %s", err.Error())
		logs.Error(errMsg)
		p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, errMsg, nil)
		p.ServeJSON()
		return
	}
	defer fp.Close()
	_, inputFileName := filepath.Split(handle.Filename)

	// 解析文件名
	soft := &dbmanager.Package{}
	err = soft.ParseFileName(inputFileName)
	if err != nil {
		errMsg := fmt.Sprintf("parse filename error: %s", err.Error())
		logs.Error(errMsg)
		p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, errMsg, nil)
		p.ServeJSON()
		return
	}

	// 临时存储文件
	destFileName := filepath.Join(ctrutil.TmpDir, ctrutil.TmpWormDir, inputFileName)
	newFp, err := os.OpenFile(destFileName, os.O_WRONLY | os.O_CREATE, 0644)
	if err != nil {
		errMsg := fmt.Sprintf("open file '%s' error: %s", destFileName, err.Error())
		logs.Error(errMsg)
		p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, errMsg, nil)
		p.ServeJSON()
		return
	}
	defer newFp.Close()
	defer os.Remove(destFileName)
	// 拷贝文件内容
	_, err = io.Copy(newFp, fp)
	if err != nil {
		errMsg := fmt.Sprintf("copy file error: %s", err.Error())
		logs.Error(errMsg)
		p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, errMsg, nil)
		p.ServeJSON()
		return
	}
	// 计算得到MD5值
	fileMD5 := ufile.GetFileMd5(destFileName)
	//logs.Debug(fmt.Sprintf("%s: %s", destFileName, fileMD5))

	// 执行文件上传到resource server
	downloadURL, err := ctrutil.ResourceSet().UploadFile(destFileName, ctrutil.UploadWormURL)
	if err != nil {
		logs.Error(err.Error())
		p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, err.Error(), nil)
		p.ServeJSON()
		return
	}

	// 处理数据
	soft.UploadUser = p.GetSession(ctrutil.SessionUserName).(string)
	soft.Md5 = fileMD5
	soft.Url = downloadURL
	soft.Status = mysqldb.StatusValid

	// db操作
	tmpSoft := &dbmanager.Package{FileName: soft.FileName}
	err = tmpSoft.Read("file_name")
	if err == nil {
		// 说明有，执行更新
		soft.Id = tmpSoft.Id
		soft.Updated = time.Now().Unix()
		err = soft.Update("upload_user", "md5", "url", "updated", "status")
		if err != nil {
			errMsg := fmt.Sprintf("update package recodr error: %s", err.Error())
			logs.Error(errMsg)
			p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, errMsg, nil)
			p.ServeJSON()
			return
		}
	} else if strings.Contains(err.Error(), mysqldb.NoMysqlRow) {
		// 说明没有，执行insert操作
		soft.Created = time.Now().Unix()
		soft.Updated = soft.Created
		err = soft.Insert()
		if err != nil {
			errMsg := fmt.Sprintf("insert package recodr error: %s", err.Error())
			logs.Error(errMsg)
			p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, errMsg, nil)
			p.ServeJSON()
			return
		}
	} else {
		errMsg := fmt.Sprintf("read package record error: %s", err.Error())
		logs.Error(errMsg)
		p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, errMsg, nil)
		p.ServeJSON()
		return
	}

	// OK结束
	p.Data["json"] = uhttp.CreateOkResponse(nil)
	p.ServeJSON()
	return
}

// PackageController.UpdatePackage 更新包的状态
func (p *PackageController) UpdateStatus() {
	p.Manager()

	type PackageInfo struct {
		Status 		int 		`json:"status"`
		Id 			int64			`json:"id"`
	}
	body, err := ioutil.ReadAll(p.Ctx.Request.Body)
	if err != nil {
		p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeReqBodyErr, err.Error(), nil)
		p.ServeJSON()
		return
	}
	var input PackageInfo
	if err = json.Unmarshal(body, &input); err != nil {
		p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeReqBodyErr, "input Unmarshal error.", nil)
		p.ServeJSON()
		return
	}
	if input.Status != mysqldb.StatusValid && input.Status != mysqldb.StatusInvalid {
		errMsg := fmt.Sprintf("input status error, must: %d/%d", mysqldb.StatusInvalid, mysqldb.StatusValid)
		logs.Error(errMsg)
		p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, errMsg, nil)
		p.ServeJSON()
		return
	}

	// 读取配置
	soft := &dbmanager.Package{Id: input.Id}
	err = soft.Read("id")
	if err != nil {
		errMsg := fmt.Sprintf("read package record '%d' error: %s", input.Id, err.Error())
		logs.Error(errMsg)
		p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, errMsg, nil)
		p.ServeJSON()
		return
	}
	// 如果有变更，则更新状态status
	if soft.Status != input.Status {
		soft.Status = input.Status
		soft.Updated = time.Now().Unix()
		err = soft.Update("status", "updated")
		if err != nil {
			errMsg := fmt.Sprintf("update package record '%d' error: %s", input.Id, err.Error())
			logs.Error(errMsg)
			p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, errMsg, nil)
			p.ServeJSON()
			return
		}
	}

	p.Data["json"] = uhttp.CreateOkResponse(nil)
	p.ServeJSON()
	return
}

func (p *PackageController) PackList()  {
	p.Manager()

	offset, limit := p.DealPage()
	status, _ := p.GetInt("status", mysqldb.StatusAll)
	uploadUser := p.GetString("upload_user", mysqldb.SelectStrAll)
	version, _ := p.GetInt("version", mysqldb.SelectIntAll)
	packType := p.GetString("pack_type", mysqldb.SelectStrAll)

	// count
	soft := dbmanager.Package{}
	count, err := soft.Count(packType, mysqldb.SelectStrAll, uploadUser, version, mysqldb.SelectStrAll, status)
	if err != nil {
		errMsg := fmt.Sprintf("worm agent soft count error: %s", err.Error())
		logs.Error(errMsg)
		data := map[string]interface{}{"total": 0, "data": []dbmanager.Package{}}
		p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, err.Error(), data)
		p.ServeJSON()
		return
	}
	if count == 0 {
		data := map[string]interface{}{"total": count, "data": []dbmanager.Package{}}
		p.Data["json"] = uhttp.CreateOkResponse(data)
		p.ServeJSON()
		return
	}

	// select
	result, err := soft.Select(offset, limit, packType, mysqldb.SelectStrAll, uploadUser, version, mysqldb.SelectStrAll, status)
	if err != nil {
		errMsg := fmt.Sprintf("worm agent soft select error: %s", err.Error())
		logs.Error(errMsg)
		data := map[string]interface{}{"total": 0, "data": []dbmanager.Package{}}
		p.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, err.Error(), data)
		p.ServeJSON()
		return
	}

	data := map[string]interface{}{"total": count, "data": result}
	p.Data["json"] = uhttp.CreateOkResponse(data)
	p.ServeJSON()
	return
}
